﻿using System;

using zijian666.Converts.Abstractions;
using zijian666.Converts.Convertor.Base;
using zijian666.Converts.Core;
using zijian666.Converts.Extensions;

namespace zijian666.Converts.Convertor;

/// <summary>
/// <seealso cref="TimeSpan" /> 转换器
/// </summary>
internal class TimeSpanConvertor : FromConvertor<TimeSpan>, IFrom<string, TimeSpan>, IFrom<IConvertible, TimeSpan>, IFrom<DateTimeOffset, TimeSpan>, IFrom<DateTime, TimeSpan>
{
    /// <summary>
    /// 时间格式化字符
    /// </summary>
    private static readonly string[] _formats = {
        "hhmmss",
        "hh\\:mm\\:ss",
        "hhmmssfff",
        "hh\\:mm\\:ss\\.fff",
        "hhmmssffffff",
        "hh\\:mm\\:ss\\.ffffff",
    };

    /// <inheritdoc/>
    public ConvertResult<TimeSpan> From(IConvertContext context, string input)
    {
        var s = input.Trim();
        if (TimeSpan.TryParse(s, out var result))
        {
            return result;
        }
        foreach (var format in _formats)
        {
            if (s.Length == format.Length)
            {
                if (TimeSpan.TryParseExact(s, format, null, System.Globalization.TimeSpanStyles.None, out result))
                {
                    return result;
                }
                break;
            }
        }
        return context.ConvertFail(this, input);
    }

    /// <inheritdoc/>
    public ConvertResult<TimeSpan> From(IConvertContext context, IConvertible input)
    {
        if (input.GetTypeCode() == TypeCode.DateTime)
        {
            var time = input.ToDateTime(context.Settings.CultureInfo);
            return new TimeSpan(0, time.Hour, time.Minute, time.Second, time.Millisecond);
        }
        return context.ConvertFail(this, input);
    }

    /// <inheritdoc/>
    public ConvertResult<TimeSpan> From(IConvertContext context, DateTimeOffset input) => input.TimeOfDay;

    /// <inheritdoc/>
    public ConvertResult<TimeSpan> From(IConvertContext context, DateTime input) => input.TimeOfDay;
}
